#include "StdAfx.h"
#include "CommandExcutor.h"
#include <memory>
#include <strsafe.h>

#define CMD_COMMAND _T("cmd.exe /c")

CommandExcutor::CommandExcutor(void) : m_hStdRd(NULL)
{
}

CommandExcutor::~CommandExcutor(void)
{
	CloseHandle(m_hStdRd);
}

BOOL CommandExcutor::Excute(LPCTSTR lpCommand, LPCTSTR lpCurentDirectory)
{
	assert(lpCommand != NULL);

	HANDLE hChildStdOutWr = NULL;
	PROCESS_INFORMATION pi = {0};

	BOOL bRet = FALSE;
	do 
	{
		SECURITY_ATTRIBUTES saAttr; 
		saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
		saAttr.bInheritHandle = TRUE; 
		saAttr.lpSecurityDescriptor = NULL; 

		if (! CreatePipe(&m_hStdRd, &hChildStdOutWr, &saAttr, 0)) 
			break;

		SetHandleInformation(m_hStdRd, HANDLE_FLAG_INHERIT, 0);
		
		STARTUPINFO st;	
		memset(&st, 0, sizeof(st));
		st.cb = sizeof(STARTUPINFO);
		st.hStdInput = GetStdHandle(STD_INPUT_HANDLE);;
		st.hStdError = hChildStdOutWr;
		st.hStdOutput = hChildStdOutWr;
		st.wShowWindow = SW_HIDE;
		st.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;

		size_t commandBuffSize = (_tcslen(lpCommand) + _tcslen(CMD_COMMAND))  + 2;
		std::auto_ptr<TCHAR> commandlineHoder(new TCHAR[commandBuffSize]);
		HRESULT hr = StringCbPrintf(commandlineHoder.get(), commandBuffSize * sizeof(TCHAR), _T("%s %s"), CMD_COMMAND, lpCommand);
		if( FAILED(hr))
			break;

		BOOL bCreated = CreateProcess(NULL,commandlineHoder.get(), NULL, NULL, TRUE, 0, NULL, lpCurentDirectory, &st, &pi);
		if (!bCreated) 
		{
			break;
		}

		bRet = TRUE;
	} while (0);

	CloseHandle(pi.hThread);
	CloseHandle(pi.hProcess);
	CloseHandle(hChildStdOutWr);	
	
	if (!bRet) 
	{
		CloseHandle(m_hStdRd);
		m_hStdRd = NULL;
	}

	return bRet;
}

BOOL CommandExcutor::GetResult(LPSTR lpBuffer, DWORD dwSize)
{
	assert(m_hStdRd != NULL);
	assert(dwSize >= 0);

	DWORD dwRead = 0;
	if( !ReadFile( m_hStdRd, lpBuffer,dwSize-1, &dwRead, NULL) || dwRead == 0) 
	{
		return FALSE;
	}
	
	lpBuffer[dwRead] = 0;
	return TRUE;
}